﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using MyUtils;

namespace FitAutomation.FitProcess
{
	public static class ProgramEntryPointImpl
	{
		static FitProcessListener _listener;
		static int _port;
		static string _mutex;
		static readonly List<Assembly> _asms = new List<Assembly>();

		public static void MainImpl()
		{
			DebugUtils.DebuggerReattaching();

			var args = Environment.GetCommandLineArgs().Skip(1).ToArray();

			Console.WriteLine("Started with args: " + args.Join(" "));

			AppDomain.CurrentDomain.AssemblyResolve += CurrentDomainAssemblyResolve;
			AppDomain.CurrentDomain.TypeResolve += CurrentDomainTypeResolve;

			try
			{
				if (args.Length > 0)
				{
					foreach (var arg in args)
					{
						var parts = arg.Split(new[] { '=' }, StringSplitOptions.RemoveEmptyEntries);
						var cmd = parts[0].ToLowerInvariant();
						Console.WriteLine("Argument: " + cmd);
						switch (cmd)
						{
							case "load":
								if (parts.Length != 2)
								{
									throw new Exception("'mutex' should have 2 sections: mutex=abc");
								}
								var file = parts[1];
								if (!Path.IsPathRooted(file))
								{
									throw new Exception("File name is not rooted: " + file);
								}
								if (File.Exists(file))
								{
									var asm = Assembly.LoadFrom(file);
									_asms.Add(asm);
								}
								else
								{
									throw new Exception("File not found: " + file);
								}
								break;
							case "mutex":
								if (parts.Length != 2)
								{
									throw new Exception("'mutex' should have 2 sections: mutex=abc");
								}
								_mutex = parts[1];
								if (_mutex.Length <= 0)
								{
									throw new Exception("mutex name not specified");
								}

								break;
							case "port":
								if (_listener == null)
								{
									if (parts.Length != 2)
									{
										throw new Exception("'port' should have 2 sections: port=213");
									}
									uint port;
									if (uint.TryParse(parts[1], out port))
									{
										_port = (int)port;

									}
									else
									{
										throw new Exception("port is invalid: " + parts[1]);
									}
								}
								else
								{
									throw new Exception("port specified 2 times");
								}
								break;
							default:
								throw new Exception("Unknown parameter: " + cmd);
						}
					}
				}

				Console.WriteLine("_port = " + _port);
				Console.WriteLine("_mutex = " + _mutex);

				_listener = new FitProcessListener(_port, _mutex);
				while (true)
				{
					Thread.Sleep(TimeSpan.FromHours(1));
				}
			}
			catch (Exception ex)
			{
				Console.WriteLine(ex.ToString());
			}

			Console.WriteLine("Stopped.");
			if (Debugger.IsAttached)
			{
				Console.ReadKey();
			}
		}

		static Assembly CurrentDomainAssemblyResolve(object sender, ResolveEventArgs args)
		{
			return _asms.FirstOrDefault(x => x.FullName == args.Name);
		}

		static Assembly CurrentDomainTypeResolve(object sender, ResolveEventArgs args)
		{
			return _asms.FirstOrDefault(x => x.FullName == args.Name);
		}
	}
}
